﻿using MsgGen;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace RosSharp.MsgGen
{
    public class GenerateHelper
    {
        private List<MsgsFile> msgsFiles = new List<MsgsFile>();
        private List<SrvsFile> srvFiles = new List<SrvsFile>();
        private string backhalf;
        private string fronthalf;
        private string uberpwnage;
        public string outputdir;

        public static void GenerateMsgAndSrv(string inputDir, string outputDir)
        {
            new GenerateHelper(inputDir, outputDir);
        }

        public GenerateHelper(string inputDir, string outputDir)
        {
            this.outputdir = outputDir;
            List<MsgFileLocation> paths = new List<MsgFileLocation>();
            List<MsgFileLocation> pathssrv = new List<MsgFileLocation>();
            Console.WriteLine("开始生成ROS Messages...\n");
            MsgFileLocator.findMessages(paths, pathssrv, inputDir);
            paths = MsgFileLocator.sortMessages(paths);
            foreach (MsgFileLocation path in paths)
            {
                msgsFiles.Add(new MsgsFile(path));
            }
            foreach (MsgFileLocation path in pathssrv)
            {
                srvFiles.Add(new SrvsFile(path));
            }
            if (paths.Count + pathssrv.Count > 0)
            {
                GenerateFiles(msgsFiles, srvFiles);
            }
        }

        public void GenerateFiles(List<MsgsFile> files, List<SrvsFile> srvfiles)
        {
            List<MsgsFile> mresolved = new List<MsgsFile>();
            List<SrvsFile> sresolved = new List<SrvsFile>();
            while (files.Except(mresolved).Any())
            {
                Debug.WriteLine("MSG: Running for " + files.Count + "/" + mresolved.Count + "\n" + files.Except(mresolved).Aggregate("\t", (o, n) => "" + o + "\n\t" + n.Name));
                foreach (MsgsFile m in files.Except(mresolved))
                {
                    string md5 = null;
                    string typename = null; ;
                    md5 = MD5.Sum(m);
                    typename = m.Name;
                    if (md5 != null && !md5.StartsWith("$") && !md5.EndsWith("MYMD5SUM"))
                    {
                        mresolved.Add(m);
                    }
                    else
                    {
                        Debug.WriteLine("Waiting for children of " + typename + " to have sums");
                    }
                }
                if (files.Except(mresolved).Any())
                {
                    Debug.WriteLine("MSG: Rerunning sums for remaining " + files.Except(mresolved).Count() + " definitions");
                }
            }
            while (srvfiles.Except(sresolved).Any())
            {
                Debug.WriteLine("SRV: Running for " + srvfiles.Count + "/" + sresolved.Count + "\n" + srvfiles.Except(sresolved).Aggregate("\t", (o, n) => "" + o + "\n\t" + n.Name));
                foreach (SrvsFile s in srvfiles.Except(sresolved))
                {
                    string md5 = null;
                    string typename = null;
                    s.Request.Stuff.ForEach(a => s.Request.resolve(s.Request, a));
                    s.Response.Stuff.ForEach(a => s.Request.resolve(s.Response, a));
                    md5 = MD5.Sum(s);
                    typename = s.Name;
                    if (md5 != null && !md5.StartsWith("$") && !md5.EndsWith("MYMD5SUM"))
                    {
                        sresolved.Add(s);
                    }
                    else
                    {
                        Debug.WriteLine("Waiting for children of " + typename + " to have sums");
                    }
                }
                if (srvfiles.Except(sresolved).Any())
                {
                    Debug.WriteLine("SRV: Rerunning sums for remaining " + srvfiles.Except(sresolved).Count() + " definitions");
                }
            }
            foreach (MsgsFile file in files)
            {
                file.Write(outputdir);
            }
            foreach (SrvsFile file in srvfiles)
            {
                file.Write(outputdir);
            }
            File.WriteAllText(outputdir + "\\MessageTypes.cs", ToString().Replace("FauxMessages", "Messages"));
        }
    }
}
